package com.atguigu.linkedlist;

public class DoubleLinkedListDemo {

    public static void main(String[] args) {

        HeroNode2 heroNode1 = new HeroNode2(1, "宋江", "及时雨");
        HeroNode2 heroNode2 = new HeroNode2(2, "林冲", "豹子头");
        HeroNode2 heroNode3 = new HeroNode2(3,"李逵","黑旋风");
        HeroNode2 heroNode4 = new HeroNode2(4,"浪里白条","张顺");

        //创建一个双向链表
        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();

        System.out.println("添加节点到双向链表");

        doubleLinkedList.add(heroNode1);
        doubleLinkedList.add(heroNode2);
        doubleLinkedList.add(heroNode3);
        doubleLinkedList.add(heroNode4);
        doubleLinkedList.show();

        System.out.println("修改后的链表");
        HeroNode2 newHerNode = new HeroNode2(3,"吴用","智多星");
        doubleLinkedList.update(newHerNode);
        doubleLinkedList.show();

//        System.out.println("测试有序添加节点且编号不可重复方法");
//        doubleLinkedList.addOrderBy(heroNode1);
//        doubleLinkedList.addOrderBy(heroNode3);
//        doubleLinkedList.addOrderBy(heroNode2);
//        doubleLinkedList.show();

        System.out.println("删除后的链表");
        doubleLinkedList.delete(2);
        doubleLinkedList.show();

    }
}
//创建一个双向链表的类
class DoubleLinkedList{

    private HeroNode2 head = new HeroNode2(0,"","");

    /*  添加节点单向链表
       当不考虑编号顺序时
       1.找到当前链表的最后节点
       2.将最后这个节点的next指向新节点
       */
    public void add(HeroNode2 heroNode){

        //head头节点不能动,因此我们需要一个辅助遍历 temp
        HeroNode2 temp = head;

        //遍历链表,找到最后
        while (true){
            if (temp.next == null){
                break;
            }

            //如果没有找到最后 将temp后移
            temp = temp.next;
        }

        //当退出while循环的时候,temp就指向了链表最后
        //将最后这个节点的next值指向新节点
        temp.next = heroNode;
        heroNode.pre = temp;
    }

    //随机插入英雄,保证编号有序且不能重复
    public void addOrderBy(HeroNode2 heroNode){

        HeroNode2 temp = head;
        boolean flag = false;

        while (true){

            if (temp.next == null){
                break;
            }

            if (temp.next.no > heroNode.no){
                break;
            }else if (temp.next.no == heroNode.no){
                flag = true;
                break;
            }

            temp = temp.next;
        }

        if (flag){
            System.out.printf("准备插入的英雄的编号 %d已经存在, 不能加入\n",heroNode.no);
        }else {
            heroNode.next = temp.next;
            if (temp.next != null){
                temp.next.pre = heroNode;
            }
            temp.next = heroNode;
            heroNode.pre = temp;
        }
    }

    //根据编号修改节点,编号不可修改
    public void update(HeroNode2 heroNode){

        //判断是否为空
        if (head.next == null){
            System.out.println("链表为空~~~");
            return;
        }

        HeroNode2 temp = head.next;
        boolean flag = false;
        while (true){

            //已经遍历完链表
            if (temp == null){
                break;
            }

            if (temp.no == heroNode.no){
                //找到
                flag = true;
                break;
            }
            temp = temp.next;
        }

        //根据flag判断是否找到要修改的节点
        if (flag) {
            temp.name = heroNode.name;
            temp.nickname = heroNode.nickname;
        }else {//没找到
            System.out.printf("没有找到 编号 %d的节点,不能修改\n",heroNode.no);
        }
    }

    public void delete(int no){

        if (head.next == null){
            System.out.println("链表为空~~~");
        }

        HeroNode2 temp = head.next;
        boolean flag = false;
        while (true){

            if (temp == null){
                break;
            }

            if (temp.no == no){
                flag = true;
                break;
            }

            temp = temp.next;
        }

        if (flag){
            temp.pre.next = temp.next;
            //这里我们的代码有问题?
            //如果删除的是链表中最后一个节点,就不需要执行这句话,否则会导致空指针异常
            if (temp.next != null){
                temp.next.pre = temp.pre;
            }else {//没找到
                System.out.printf("没有找到 编号 %d的节点,不能修改\n",no);
            }

        }
    }

    public void show(){
        //判断链表是否为空
        if (head.next == null){
            System.out.println("链表为空~~~");
            return;
        }

        HeroNode2 temp = head.next;

        while (true){
            //判断是否到了链表最后
            if (temp == null){
                break;
            }

            System.out.println(temp);

            //将temp后移,一定小心
            temp = temp.next;
        }
    }
}

//定义HeroNode ， 每个HeroNode 对象就是一个节点
class HeroNode2 {
    public int no;
    public String name;
    public String nickname;
    public HeroNode2 next; //指向下一个节点 默认为null
    public HeroNode2 pre; //指向上一个节点 默认为null

    //构造器
    public HeroNode2(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    //为了显示方法，我们重新toString


    @Override
    public String toString() {
        return "HeroNode2{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}